<?php

namespace App\Admin\Forms\Aliyun;

use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Dcdn\Dcdn;
use App\Enums\BucketType;
use App\Enums\DnsType;
use App\Enums\DomainSource;
use App\Enums\DomainType;
use App\Facades\AliyunDns;
use App\Jobs\CreateAliyunDcdn;
use App\Models\Aliyun;
use App\Models\Application;
use App\Models\DomainPool;
use App\Models\ObjectStorageService;
use Dcat\Admin\Admin;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Exception\RuntimeException;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Str;

abstract class DcdnForm extends Form implements LazyRenderable
{
    use LazyWidget;

    /**
     * @throws ServerException
     * @throws ClientException
     */
    public function baseHandle(array $input, DomainType $domainType)
    {
        if ($input['source'] == DomainSource::ALIYUN->value) {
            if (!Str::startsWith($input['rr'], '*.')) {
                $input['rr'] = '*.'.$input['rr'];
            }

            if (DomainPool::where('domain', $input['rr'].'.'.$input['root'])->exists()) {
                return $this->response()->error('域名必须全局唯一');
            }

            if ($input['aliyun_id'] != ObjectStorageService::ofAdmin()->find($input['oss_id'])->aliyun_id) {
                ObjectStorageService::ofAdmin()->find($input['oss_id'])->aliyun->initClient();
                try {
                    Dcdn::v20180115()
                        ->verifyDcdnDomainOwner()
                        ->withDomainName(str_replace('*', '', $input['rr'].'.'.$input['root']))
                        ->withVerifyType('dnsCheck')
                        ->request();
                } catch (ClientException|ServerException) {
                    $content = Dcdn::v20180115()
                        ->describeDcdnVerifyContent()
                        ->withDomainName(str_replace('*', '', $input['rr'].'.'.$input['root']))
                        ->request()
                        ->get('Content');

                    AliyunDns::aliyun(Aliyun::ofAdmin()->find($input['aliyun_id']))
                        ->store($input['root'], 'verification', $content, DnsType::TXT);
                }
            }

            $data = [
                'source' => $input['source'],
                'aliyun_id' => $input['aliyun_id'],
                'type' => $domainType,
                'domain' => $input['rr'].'.'.$input['root'],
                'rr' => $input['rr'],
                'root' => $input['root'],
                'oss_id' => $input['oss_id'],
                'status' => $input['status'],
                'ssl' => $input['ssl'],
            ];
        } else {
            if (!Str::startsWith($input['domain'], '*.')) {
                return $this->response()->error('域名必须以 "*." 开头');
            }

            $domain = $input['domain'];
            if (DomainPool::where('domain', $domain)->exists()) {
                return $this->response()->error('域名必须全局唯一');
            }
            $data = [
                'source' => $input['source'],
                'type' => $domainType,
                'domain' => $domain,
                'status' => $input['status'],
                'ssl' => $input['ssl'],
            ];
        }

        if (Admin::user()->isAdministrator()) {
            $data['application_id'] = $input['application_id'];
        }

        $pool = DomainPool::ofAdmin()->create($data);

        if ($input['source'] == DomainSource::ALIYUN->value) {
            CreateAliyunDcdn::dispatch($pool);
        }

        return $this->response()->success('操作成功')->refresh();
    }

    /**
     * @throws RuntimeException
     */
    protected function baseForm(BucketType $bucketType): void
    {
        if (Admin::user()->isAdministrator()) {
            $this->select('application_id', '所属应用')
                ->required()
                ->options(Application::ofEnabled()->pluck('name', 'id'));
        }
        $this->radio('source', '域名来源')
            ->required()
            ->options(DomainSource::SOURCE_MAP)
            ->default(DomainSource::ALIYUN->value)
            ->when(DomainSource::CUSTOM->value, function ($form) {
                $form->text('domain', '域名地址')
                    ->help('活码域名一定要使用泛解析 *. 开始的记录')
                    ->rules('required_if:source,'.DomainSource::CUSTOM->value, [
                        'required_if' => '域名地址必须填写，且必须是泛解析',
                    ]);
            })
            ->when(DomainSource::ALIYUN->value, function ($form) use ($bucketType) {
                $form->select('aliyun_id', '云账户')
                    ->rules('required_if:source,'.DomainSource::ALIYUN->value)
                    ->options(Aliyun::ofAdmin()->pluck('name', 'id'))
                    ->load('root', route('admin.pools.domains'));
                $form->select('root', '根域名')
                    ->rules('required_if:source,'.DomainSource::ALIYUN->value);

                if ($bucketType == BucketType::RANK || $bucketType == BucketType::PLAYER) {
                    $form->text('rr', 'A记录')
                        ->prepend('*.')
                        ->help('泛解析记录，系统自动添加 "*." 前缀')
                        ->rules('required_if:source,'.DomainSource::ALIYUN->value);
                } else {
                    $form->text('rr', 'A记录')
                        ->rules('required_if:source,'.DomainSource::ALIYUN->value);
                }

                $this->select('oss_id', '存储空间')
                    ->help('存储空间关系到前台展示的版本')
                    ->rules('required_if:source,'.DomainSource::ALIYUN->value)
                    ->options(
                        ObjectStorageService::ofAdmin()
                            ->where('type', $bucketType)
                            ->pluck('bucket', 'id')
                    );
            });
        $this->switch('status')
            ->default(true);
        $this->switch('ssl', '开启SSL')
            ->help('SSL可以有效防止DNS污染拦截，开通SSL需要提供SSL证书，联系管理员单独配置')
            ->readOnly();
    }
}
